package com.jumi.microservice.rocketmq;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.ons.api.Action;
import com.aliyun.openservices.ons.api.ConsumeContext;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.MessageListener;
import com.aliyun.openservices.ons.api.bean.ProducerBean;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jumi.microservice.common.enumeration.CommonResponseEnum;
import com.jumi.microservice.common.exception.BaseException;
import com.jumi.microservice.domain.GoodsStockQuery;
import com.jumi.microservice.domain.MessageTemplate;
import com.jumi.microservice.dto.invoice.InvoiceAddRequest;
import com.jumi.microservice.dto.order.OrderGoodsMessage;
import com.jumi.microservice.dto.order.OrderLogRequest;
import com.jumi.microservice.dto.order.OrderMessage;
import com.jumi.microservice.entity.OrderGoods;
import com.jumi.microservice.entity.UserOrder;
import com.jumi.microservice.enumerate.OrderStatusEnum;
import com.jumi.microservice.mapper.OrderGoodsMapper;
import com.jumi.microservice.mapper.UserOrderMapper;
import com.jumi.microservice.service.IOrderDubboService;
import com.jumi.microservice.service.IWalletInOrOutService;
import com.jumi.microservice.service.IWalletInvoiceService;
import com.jumi.microservice.service.PaymentService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author Dirk
 * @Date 2020-07-17 14:01
 */
@Component
public class RocketMqOrderListener implements MessageListener {

    private static final Logger log = LoggerFactory.getLogger(RocketMqOrderListener.class);

    @Resource
    private UserOrderMapper userOrderMapper;

    @Resource
    private OrderGoodsMapper orderGoodsMapper;

    @Resource
    ProducerBean producerBean;
    @Autowired
    RocketMqConfig rocketMqConfig;

    @DubboReference
    private IOrderDubboService orderDubboService;

    @DubboReference
    private PaymentService paymentService;

    @DubboReference
    private IWalletInvoiceService walletInvoiceService;

    @DubboReference
    private IWalletInOrOutService iWalletInOrOutService;

    @Resource
    SendMessageHandler sendMessageHandler;

    @Resource
    private RedisTemplate<String,String> redisTemplate;

    private static final String key = "isPayOrder::";

    @Override
    public Action consume(Message message, ConsumeContext consumeContext) {
        String messageStr = new String(message.getBody());
        log.info("从pay队列收到消息：[{}]", messageStr);
        JSONObject jsonObject;
        try {
            jsonObject = JSON.parseObject(messageStr);
        } catch (Exception e) {
            log.error("JSON解析消息出错 [{}]",e.getMessage());
            return Action.CommitMessage;
        }
        String payNo = jsonObject.getString("payNo");
        String thirdPartyPaySn = jsonObject.getString("thirdPartyPaySn");
        Boolean res = redisTemplate.opsForValue().setIfAbsent(key+payNo+thirdPartyPaySn,"支付订单",7, TimeUnit.DAYS);
        if(res!=null && !res){
            log.info("重复支付：[{}]", payNo+thirdPartyPaySn);
            return Action.CommitMessage;
        }
        // 查询订单及商品
        QueryWrapper<UserOrder> userOrderQw = new QueryWrapper<>();
        userOrderQw.in("pay_no", payNo);
        userOrderQw.eq("order_status", OrderStatusEnum.READY_TO_PAY.getCode());
        List<UserOrder> userOrderList = userOrderMapper.selectList(userOrderQw);
        if (userOrderList.isEmpty()) {
            return Action.CommitMessage;
        }
        QueryWrapper<OrderGoods> orderGoodsQw = new QueryWrapper<>();
        List<Integer> orderIds = userOrderList.stream().map(UserOrder::getId).collect(Collectors.toList());
        orderGoodsQw.in("order_id", orderIds);
        List<OrderGoods> orderGoodsList = orderGoodsMapper.selectList(orderGoodsQw);
        try {
            // 确认库存
            orderGoodsList.forEach(orderGoods -> {
                GoodsStockQuery goodsStockQuery = new GoodsStockQuery();
                goodsStockQuery.setGoodsSkuId(orderGoods.getGoodsId());
                goodsStockQuery.setOrderSn(userOrderList.stream()
                        .filter(order -> order.getId().equals(orderGoods.getOrderId()))
                        .findFirst().orElse(new UserOrder()).getOrderNo());
                goodsStockQuery.setId(Long.valueOf(orderGoods.getWarehouseSn()));
                goodsStockQuery.setWarehouseId(orderGoods.getRealWarehouse());
                goodsStockQuery.setLockedStockQuantity(orderGoods.getGoodsAmount());
                goodsStockQuery.setSaledStockQuantity(orderGoods.getGoodsAmount());
                log.info("支付 请求确认库存参数 {}", JSON.toJSONString(goodsStockQuery));
                paymentService.paymentService(goodsStockQuery);
            });
        } catch (Exception e) {
            redisTemplate.delete(key+payNo+thirdPartyPaySn);
            log.error("支付确认库存调用出错 {}", e.getMessage());
            return Action.ReconsumeLater;
        }

        // 修改订单状态
        UserOrder userOrder = new UserOrder();
        userOrder.setOrderStatus(OrderStatusEnum.READY_TO_SHIP.getCode());
        userOrder.setThirdPartyPaySn(thirdPartyPaySn);
        userOrder.setPayTime(new Date());
        int rows = userOrderMapper.update(userOrder, userOrderQw);
        if (rows <= 0) {
            redisTemplate.delete(key+payNo+thirdPartyPaySn);
            log.error("订单状态更改失败");
            throw new BaseException(CommonResponseEnum.SERVER_ERROR);
        }
        // 修改商品状态
        OrderGoods goods = new OrderGoods();
        goods.setGoodsStatus(new Byte("0"));
        rows = orderGoodsMapper.update(goods, orderGoodsQw);
        if(rows <= 0){
            redisTemplate.delete("isPayOrder::"+payNo+thirdPartyPaySn);
            log.error("订单商品状态更改失败");
            throw new BaseException(CommonResponseEnum.SERVER_ERROR);
        }

        // 记录订单支付日志
        for (UserOrder order : userOrderList) {
            addOrderLog(order, payNo);
            // 添加发票
            addOrderInvoice(order);
            // 发送消息
            sendMessage(order, orderGoodsList);
        }
        return Action.CommitMessage;
    }

    private void addOrderLog(UserOrder order, String payNo) {
        order.setOrderStatus(OrderStatusEnum.READY_TO_SHIP.getCode());
        OrderLogRequest orderLogRequest = new OrderLogRequest();
        orderLogRequest.setOperatorId(order.getBuyerId());
        orderLogRequest.setOperatorName("买家");
        orderLogRequest.setOrderSn(order.getOrderNo());
        orderLogRequest.setUserFlag(new Byte("1"));
        orderLogRequest.setLog("支付订单-".concat(payNo));
        orderDubboService.addOrderLog(orderLogRequest);
    }

    private void addOrderInvoice(UserOrder order) {
        InvoiceAddRequest invoiceAddRequest = new InvoiceAddRequest();
        invoiceAddRequest.setUid(order.getBuyerId());
        invoiceAddRequest.setOrderNum(order.getOrderNo());
        invoiceAddRequest.setOrderId(order.getId());
        invoiceAddRequest.setInvoiceId(order.getInvoiceId());
        invoiceAddRequest.setInvoiceAmount(order.getPayAmount().subtract(order.getFreightFee()));
        walletInvoiceService.addOrderInvoice(invoiceAddRequest);
    }

    public void sendMessage(UserOrder order, List<OrderGoods> orderGoodsList) {
        OrderMessage orderMessage = new OrderMessage();
        BeanUtils.copyProperties(order, orderMessage);
        List<OrderGoods> subOrderGoodsList = orderGoodsList.stream()
                .filter(orderGoods -> orderGoods.getOrderId().equals(order.getId()))
                .collect(Collectors.toList());
        List<OrderGoodsMessage> orderGoodsMessageList = new ArrayList<>();
        subOrderGoodsList.forEach(orderGoods -> {
            OrderGoodsMessage orderGoodsMessage = new OrderGoodsMessage();
            BeanUtils.copyProperties(orderGoods, orderGoodsMessage);
            orderGoodsMessage.setFixRebate(orderGoods.getFixRebate());
            orderGoodsMessageList.add(orderGoodsMessage);
        });
        orderMessage.setOrderGoodsList(orderGoodsMessageList);
        log.info("往order队列发送消息[{}]", JSON.toJSONString(orderMessage));
        Message message = new Message(rocketMqConfig.getTopic(), "", "", JSONObject.toJSONBytes(orderMessage));
        producerBean.send(message);
        //推送消息给用户
        MessageTemplate messageTemplate = sendMessageHandler.getMessageTemplate(1);
            String appMessageContent = messageTemplate==null?"":messageTemplate.getSmtAppContent()
                    .replace("{}", order.getReceiverAddress());
            String stationMessageContent = messageTemplate==null?"":messageTemplate.getSmtMessageContent()
                    .replace("{}", order.getReceiverAddress());
        sendMessageHandler.sendMessage(order.getOrderNo(), appMessageContent, stationMessageContent,
                "", "", "", orderGoodsList.get(0).getGoodsCoverImg(),
                order.getBuyerId(), 1, BigDecimal.ZERO, BigDecimal.ZERO, "", (byte) 0);
    }

}
